We may have a finally block in conjunction with a try block without a catch block. In other words, it is possible to eliminate the catch block totally in our program code. The syntax for this is shown here:
try {
blockStatementsopt
} finally {
blockStatementsopt
}
In such a case, our code would have the following structure:
try {
// some code
} finally {
// free resources
}
This is typically used for freeing resources used in the try block.
It would always be executed regardless of whether or not the code in the try block generates an error.
Now, if an error occurs in the code specified in the try block, the program tries to find an appropriate exception handler in the code; however, because no handler is found, the current thread terminates. Before terminating the thread, the program executes the finally clause specified in our code. After this, it also executes the uncaughtException method in the ThreadGroup object to which the current thread belongs.
The fact that the Exception object is thrown to the outer code can be used to our advantage in separating out the error-handling code from the resource-freeing code. This is shown in the following code block:
try {
try {
// some code
} finally {
// free resources
}
} catch (Exception e) {
// handle exceptions
}
If an exception occurs in the inner try block, it is caught in the exception handler provided by the outer try block. Thus, the code in the finally block becomes solely responsible for cleaning up resources while the code in the catch block takes the responsibility of handling exceptions. In fact, if the code in the finally block were to generate an exception, it would also be caught and handled in the catch block.
There is one design flaw in Java’s finally syntax. The finally block allows us to include one of the jump statements, such as break. If the finally block is entered from a throw statement, which we will discuss in later posts, the execution of a break, continue, or return statement in the finally block overrides the throw statement and aborts the error handling. Note that the finally block does not have access to the Exception object and therefore cannot determine whether it has been entered as a result of a throw statement or due to another cause.
However, C# takes care of this flaw in Java by prohibiting the use of any jump statements in a finally block. When a return statement is executed in our code, the finally block is never executed. If an exception occurs in the finally block, the original exception generated in the corresponding try block is lost.
Another important point we should note here is that the finally block cannot handle errors. As stated earlier, it does not have access to the Exception object or any of the objects referenced by it. Therefore, it cannot log an error, diagnose it, or apply any corrections. It does not even know whether it was entered normally or as a result of an error. The philosophy behind a finally block is to free the resources and clean up any mess that the code might have created. It is typically used to achieve unconditional error cancellation.
Allen Scott
20-Apr-2017